home *** CD-ROM | disk | FTP | other *** search
- #define LIBQBUILD_CORE
- #include "../include/libqbuild.h"
-
- /*
- *
- * input
- * -----
- * vertexes
- * edges
- * faces
- *
- * output
- * ------
- * smaller set of vertexes
- * smaller set of edges
- * regions
- * ? triangulated regions
- * face to region mapping numbers
- *
- */
-
- typedef struct {
- int numedges;
- int edges[2];
- } __packed checkpoint_t; // 12
-
- int firstedge; // 4
-
- vec3_t region_mins, region_maxs; // 24
-
- /* changed by niels */
- #ifdef EDGEMAPPING
- int edgemapping[MAX_MAP_EDGES]; // 172032
- #endif
-
- checkpoint_t *checkpoints;
-
- void AddPointToRegion(register vec3_t p)
- {
- short int i;
-
- for (i = 0; i < 3; i++) {
- if (p[i] < region_mins[i])
- region_mins[i] = p[i];
- if (p[i] > region_maxs[i])
- region_maxs[i] = p[i];
- }
- }
-
- void ClearRegionSize(void)
- {
- region_mins[0] = region_mins[1] = region_mins[2] = 9999;
- region_maxs[0] = region_maxs[1] = region_maxs[2] = -9999;
- }
-
- void AddFaceToRegionSize(register struct visfacet * f)
- {
- int i;
-
- for (i = 0; i < f->numpoints; i++)
- AddPointToRegion(f->pts[i]);
- }
-
- /*
- * ==============
- * CanJoinFaces
- * ==============
- */
- bool CanJoinFaces(__memBase, register struct visfacet * f, register struct visfacet * f2)
- {
- vec3_t oldmins, oldmaxs;
- short int i;
-
- if (f2->planenum != f->planenum
- || f2->planeside != f->planeside
- || f2->texturenum != f->texturenum)
- return FALSE;
- if (f2->outputnumber != -1)
- return FALSE;
- if (f2->contents[0] != f->contents[0]) { // does this ever happen? theyy shouldn't share.
-
- eprintf("CanJoinFaces: edge with different contents");
- return FALSE;
- }
-
- // check size constraints
- if (!(bspMem->texinfo[f->texturenum].flags & TEX_SPECIAL)) {
- VectorCopy(region_mins, oldmins);
- VectorCopy(region_maxs, oldmaxs);
- AddFaceToRegionSize(f2);
- for (i = 0; i < 3; i++) {
- if (region_maxs[i] - region_mins[i] > 240) {
- VectorCopy(oldmins, region_mins);
- VectorCopy(oldmaxs, region_maxs);
- return FALSE;
- }
- }
- }
- else {
- if (bspMem->numsurfedges - firstedge + f2->numpoints > MAX_EDGES_IN_REGION)
- return FALSE; // a huge water or sky polygon
-
- }
-
- // check edge count constraints
- return TRUE;
- }
-
- /*
- * ==============
- * RecursiveGrowRegion
- * ==============
- */
- void RecursiveGrowRegion(__memBase, register struct dface_t * r, register struct visfacet * f)
- {
- int e;
- struct visfacet *f2;
- int i;
-
- if (f->outputnumber == bspMem->numfaces)
- return;
-
- if (f->outputnumber != -1)
- Error("RecursiveGrowRegion: region collision");
- f->outputnumber = bspMem->numfaces;
-
- // add edges
- for (i = 0; i < f->numpoints; i++) {
- e = f->edges[i];
- /* if (!edgefaces[abs(e)][0]) */
- if (!bspMem->edgefaces[0][abs(e)])
- continue; // edge has allready been removed
-
- if (e > 0)
- /* f2 = edgefaces[e][1]; */
- f2 = bspMem->edgefaces[1][e];
- else
- /* f2 = edgefaces[-e][0]; */
- f2 = bspMem->edgefaces[0][-e];
- if (f2 && f2->outputnumber == bspMem->numfaces) {
- /* edgefaces[abs(e)][0] = NULL; */
- bspMem->edgefaces[0][abs(e)] = NULL;
- /* edgefaces[abs(e)][1] = NULL; */
- bspMem->edgefaces[1][abs(e)] = NULL;
- continue; // allready merged
-
- }
- if (f2 && CanJoinFaces(bspMem, f, f2)) { // remove the edge and merge the faces
-
- /* edgefaces[abs(e)][0] = NULL; */
- bspMem->edgefaces[0][abs(e)] = NULL;
- /* edgefaces[abs(e)][1] = NULL; */
- bspMem->edgefaces[1][abs(e)] = NULL;
- RecursiveGrowRegion(bspMem, r, f2);
- }
- else {
- // emit a surfedge
- if (bspMem->numsurfedges == bspMem->max_numsurfedges)
- ExpandClusters(bspMem, LUMP_SURFEDGES);
- bspMem->dsurfedges[bspMem->numsurfedges] = e;
- bspMem->numsurfedges++;
- }
- }
-
- }
-
- #ifdef DEBUG
- void PrintDface(register int f)
- { // for debugging
-
- struct dface_t *df;
- struct dedge_t *e;
- int i, n;
-
- df = &bspMem->dfaces[f];
- for (i = 0; i < df->numedges; i++) {
- n = bspMem->dsurfedges[df->firstedge + i];
- e = &bspMem->dedges[abs(n)];
- if (n < 0)
- mprintf("%5i = %5i : %5i\n", n, e->v[1], e->v[0]);
- else
- mprintf("%5i = %5i : %5i\n", n, e->v[0], e->v[1]);
- }
- }
-
- void FindVertexUse(register int v)
- { // for debugging
-
- int i, j, n;
- struct dface_t *df;
- struct dedge_t *e;
-
- for (i = firstmodelface; i < bspMem->numfaces; i++) {
- df = &bspMem->dfaces[i];
- for (j = 0; j < df->numedges; j++) {
- n = bspMem->dsurfedges[df->firstedge + j];
- e = &bspMem->dedges[abs(n)];
- if (e->v[0] == v || e->v[1] == v) {
- mprintf("on face %i\n", i);
- break;
- }
- }
- }
- }
-
- void FindEdgeUse(register int v)
- { // for debugging
-
- int i, j, n;
- struct dface_t *df;
-
- for (i = firstmodelface; i < bspMem->numfaces; i++) {
- df = &bspMem->dfaces[i];
- for (j = 0; j < df->numedges; j++) {
- n = bspMem->dsurfedges[df->firstedge + j];
- if (n == v || -n == v) {
- mprintf("on face %i\n", i);
- break;
- }
- }
- }
- }
- #endif
-
- /*
- * ================
- * HealEdges
- *
- * Extends e1 so that it goes all the way to e2, and removes all references
- * to e2
- * ================
- */
- void HealEdges(register int e1, int register e2)
- {
- int i, j, n, saved;
- struct dface_t *df;
- struct dedge_t *ed, *ed2;
- vec3_t v1, v2;
- struct dface_t *found[2];
- int foundj[2];
-
- /*
- * FIX!!! why this? niels
- */
- /* changed by niels */
- #ifdef EDGEMAPPING
- e1 = edgemapping[e1];
- e2 = edgemapping[e2];
-
- // extend e1 to e2
- ed = &bspMem->dedges[e1];
- ed2 = &bspMem->dedges[e2];
- VectorSubtract(bspMem->dvertexes[ed->v[1]].point, bspMem->dvertexes[ed->v[0]].point, v1);
- VectorNormalize(v1);
-
- if (ed->v[0] == ed2->v[0])
- ed->v[0] = ed2->v[1];
- else if (ed->v[0] == ed2->v[1])
- ed->v[0] = ed2->v[0];
- else if (ed->v[1] == ed2->v[0])
- ed->v[1] = ed2->v[1];
- else if (ed->v[1] == ed2->v[1])
- ed->v[1] = ed2->v[0];
- else
- Error("HealEdges: edges don't meet");
-
- VectorSubtract(bspMem->dvertexes[ed->v[1]].point, bspMem->dvertexes[ed->v[0]].point, v2);
- VectorNormalize(v2);
-
- if (!VectorCompare(v1, v2))
- Error("HealEdges: edges not colinear");
-
- edgemapping[e2] = e1;
- saved = 0;
-
- // remove all uses of e2
- for (i = firstmodelface; i < bspMem->numfaces; i++) {
- df = &bspMem->dfaces[i];
- for (j = 0; j < df->numedges; j++) {
- n = bspMem->dsurfedges[df->firstedge + j];
- if (n == e2 || n == -e2) {
- found[saved] = df;
- foundj[saved] = j;
- saved++;
- break;
- }
- }
- }
-
- if (saved != 2)
- eprintf("didn't find both faces for a saved edge\n");
- else {
- for (i = 0; i < 2; i++) { // remove this edge
-
- df = found[i];
- j = foundj[i];
- for (j++; j < df->numedges; j++)
- bspMem->dsurfedges[df->firstedge + j - 1] =
- bspMem->dsurfedges[df->firstedge + j];
- bspMem->dsurfedges[df->firstedge + j - 1] = 0;
- df->numedges--;
- }
-
- /* edgefaces[e2][0] = edgefaces[e2][1] = NULL; */
- bspMem->edgefaces[0][e2] = bspMem->edgefaces[1][e2] = NULL;
- }
- #else
- return;
- #endif
- }
-
- /*
- * ==============
- * RemoveColinearEdges
- * ==============
- */
- void RemoveColinearEdges(__memBase)
- {
- int i, v;
- short int j;
- int c0, c1, c2, c3;
- checkpoint_t *cp;
-
- /* changed by niels */
- #ifdef EDGEMAPPING
- // no edges remapped yet
- for (i = 0; i < bspMem->numedges; i++)
- edgemapping[i] = i;
- #endif
-
- // find vertexes that only have two edges
- /* added by niels */
- if(!(checkpoints = (checkpoint_t *)tmalloc(sizeof(checkpoint_t) * bspMem->numvertexes)))
- Error("RemoveColinearEdges: failed to allocate checkpoints!\n");
-
- for (i = firstmodeledge; i < bspMem->numedges; i++) {
- /* if (!edgefaces[i][0]) */
- if (!bspMem->edgefaces[0][i])
- continue; // removed
-
- for (j = 0; j < 2; j++) {
- v = bspMem->dedges[i].v[j];
- cp = &checkpoints[v];
- if (cp->numedges < 2)
- cp->edges[cp->numedges] = i;
- cp->numedges++;
- }
- }
-
- // if a vertex only has two edges and they are colinear, it can be removed
- c0 = c1 = c2 = c3 = 0;
-
- for (i = 0; i < bspMem->numvertexes; i++) {
- cp = &checkpoints[i];
- switch (cp->numedges) {
- case 0:
- c0++;
- break;
- case 1:
- c1++;
- break;
- case 2:
- c2++;
- HealEdges(cp->edges[0], cp->edges[1]);
- break;
- default:
- c3++;
- break;
- }
- }
-
- // mprintf ("%5i c0\n", c0);
- // mprintf ("%5i c1\n", c1);
- // mprintf ("%5i c2\n", c2);
- // mprintf ("%5i c3+\n", c3);
- mprintf("%5i edges removed by tjunction healing\n", c2);
- /* added by niels */
- tfree(checkpoints);
- }
-
- /*
- * ==============
- * CountRealNumbers
- * ==============
- */
- void CountRealNumbers(__memBase)
- {
- int i;
- int c;
-
- mprintf("%5i regions\n", bspMem->numfaces - firstmodelface);
-
- c = 0;
- for (i = firstmodelface; i < bspMem->numfaces; i++)
- c += bspMem->dfaces[i].numedges;
- mprintf("%5i real marksurfaces\n", c);
-
- c = 0;
- for (i = firstmodeledge; i < bspMem->numedges; i++)
- /* if (edgefaces[i][0]) */
- if (bspMem->edgefaces[0][i])
- c++; // not removed
-
- mprintf("%5i real edges\n", c);
- }
-
- //=============================================================================
-
- /*
- * ==============
- * GrowNodeRegion_r
- * ==============
- */
- void GrowNodeRegion_r(__memBase, register struct node * node)
- {
- struct dface_t *r;
- struct visfacet *f;
- int i;
-
- if (node->planenum == PLANENUM_LEAF)
- return;
-
- node->firstface = bspMem->numfaces;
-
- for (f = node->faces; f; f = f->next) {
- // if (f->outputnumber != -1)
- // continue; // allready grown into an earlier region
-
- // emit a region
-
- if (bspMem->numfaces == bspMem->max_numfaces)
- ExpandClusters(bspMem, LUMP_FACES);
- f->outputnumber = bspMem->numfaces;
- r = &bspMem->dfaces[bspMem->numfaces];
-
- r->planenum = node->outputplanenum;
- r->side = f->planeside;
- r->texinfo = f->texturenum;
- for (i = 0; i < MAXLIGHTMAPS; i++)
- r->styles[i] = 255;
- r->lightofs = -1;
-
- // add the face and mergable neighbors to it
-
- #if 0
- ClearRegionSize();
- AddFaceToRegionSize(f);
- RecursiveGrowRegion(r, f);
- #endif
- r->firstedge = firstedge = bspMem->numsurfedges;
- for (i = 0; i < f->numpoints; i++) {
- if (bspMem->numsurfedges == bspMem->max_numsurfedges)
- ExpandClusters(bspMem, LUMP_SURFEDGES);
- bspMem->dsurfedges[bspMem->numsurfedges] = f->edges[i];
- bspMem->numsurfedges++;
- }
-
- r->numedges = bspMem->numsurfedges - r->firstedge;
-
- bspMem->numfaces++;
- }
-
- node->numfaces = bspMem->numfaces - node->firstface;
-
- GrowNodeRegion_r(bspMem, node->children[0]);
- GrowNodeRegion_r(bspMem, node->children[1]);
- }
-
- /*
- * ==============
- * GrowNodeRegions
- * ==============
- */
- void GrowNodeRegions(__memBase, struct node * headnode)
- {
- mprintf("----- GrowRegions -------\n");
-
- GrowNodeRegion_r(bspMem, headnode);
-
- //RemoveColinearEdges ();
- CountRealNumbers(bspMem);
- }
-
- /*
- * ===============================================================================
- *
- * Turn the faces on a plane into optimal non-convex regions
- * The edges may still be split later as a result of tjunctions
- *
- * typedef struct
- * {
- * vec3_t dir;
- * vec3_t origin;
- * vec3_t p[2];
- * }
- * for all faces
- * for all edges
- * for all edges so far
- * if overlap
- * split
- *
- *
- * ===============================================================================
- */
-